import type {
  ProgressOptions,
  ProgressState,
  ProgressStep,
} from './types'
import { ThemeVarService } from '../../../../../../../../lib/abstract/style/theme_var/service'
import {
  createStandardStyleTag,
  removeStandardStyleTag,
} from '../../../../../../../../lib/style_injector'
import { TimerManager } from '../../../../../../../../lib/timer_manager'
import { ToolKit } from '../../../../../../../../lib/utils/toolkit'
import {
  ComponentStyleId,
  logger,
  PROJECT_PREFIX,
} from '../../../../../../../../types/constants'
import { SYMBOLS } from '../../../../../../../../types/interfaces'
import {
  DEFAULT_PROGRESS_STATE,
  ProgressStage,
} from './types'

/**
 * 进度管理器
 */
export class ProgressManager {
  // @Decorators.Identity
  readonly id: string = 'progress-manager'
  readonly name: string = 'ProgressManager'
  // @Decorators.PublicState
  private static instance: ProgressManager
  // @Decorators.Dependency
  private readonly timerManager: TimerManager = TimerManager.getInstance()
  private readonly themeVarService: ThemeVarService = ThemeVarService.getInstance()
  // @Decorators.UIElement
  private readonly containerClassName: string = 'progress-manager'
  private readonly cssStyleId: string = ComponentStyleId.ProgressManager
  private $progressElement: JQuery<HTMLElement> | null = null
  // @Decorators.Config
  private options: Required<ProgressOptions>
  private predefinedSteps: ProgressStep[] = [ // 预定义步骤
    {
      stage: ProgressStage.COLLECTING,
      targetPercentage: 30,
      defaultMessage: '正在收集数据...',
      icon: SYMBOLS.UI.SEARCH,
      color: 'info',
    },
    {
      stage: ProgressStage.ANALYZING,
      targetPercentage: 60,
      defaultMessage: '正在分析数据...',
      icon: SYMBOLS.UI.CHART,
      color: 'warning',
    },
    {
      stage: ProgressStage.RENDERING,
      targetPercentage: 80,
      defaultMessage: '正在生成报告...',
      icon: SYMBOLS.UI.COMPUTER,
      color: 'success',
    },
    {
      stage: ProgressStage.COMPLETE,
      targetPercentage: 100,
      defaultMessage: '完成！',
      icon: SYMBOLS.STATUS.SUCCESS,
      color: 'success',
    },
  ]

  // @Decorators.Interval
  private readonly timeUpdateTaskId: string = `${this.id}@progress-time-update`
  // @Decorators.TemporaryState
  private currentState: ProgressState // 状态管理
  // previousState: ProgressState
  private isVisible: boolean = false
  private startTime: number = 0
  // 取消状态
  private _isCancelled: boolean = false
  private cancelCallbacks: (() => void)[] = []
  // 运行时间相关
  private elapsedTime: number = 0

  /**
   * 构造函数
   */
  constructor(options: ProgressOptions = {}) {
    this.options = {
      ...DEFAULT_PROGRESS_STATE,
      ...options,
    }

    // 初始化状态
    this.currentState = this.createInitialState()
  }

  /**
   * 获取单例实例
   */
  public static getInstance(options?: ProgressOptions): ProgressManager {
    if (!ProgressManager.instance) {
      ProgressManager.instance = new ProgressManager(options)
    }
    return ProgressManager.instance
  }

  /**
   * 创建初始状态
   */
  private createInitialState(): ProgressState {
    return {
      stage: ProgressStage.IDLE,
      message: '准备就绪',
      percentage: 0,
      details: '',
      timestamp: Date.now(),
    }
  }

  /**
   * 启动进度管理器
   */
  public start(onCancel: () => void = () => {}): void {
    // 初始化进度管理器
    this.initialize()
    this.show()
    // 重置取消状态
    this.resetCancellation()
    // 启动时间更新
    this.startTimeUpdate()
    // 注册取消回调
    this.onCancel(() => {
      onCancel()
    })
  }

  /**
   * 初始化进度管理器
   */
  public initialize(): void {
    if (this.$progressElement) {
      logger.warn(`[${this.name}] 进度管理器已初始化`)
      return
    }

    try {
      this.renderProgressElement()
      logger.info(`[${this.name}] 进度管理器初始化完成`)
    }
    catch (error) {
      logger.error(`[${this.name}] 进度管理器初始化失败`, error)
    }
  }

  /**
   * 渲染进度元素
   */
  private renderProgressElement(): void {
    const $container = $(this.options.containerSelector)
    if (!$container.length) {
      throw new Error(`容器选择器 "${this.options.containerSelector}" 未找到`)
    }

    // 创建进度元素
    this.$progressElement = $(`
      <div class="${this.containerClassName}">
        <div class="progress-header">
          <span class="progress-icon"></span>
          <span class="progress-message">${this.currentState.message}</span>
          <div class="progress-stats">
            ${this.options.showPercentage ? '<span class="progress-percentage">0%</span>' : ''}
            ${this.options.showElapsedTime ? '<span class="progress-time">0秒</span>' : ''}
          </div>
        </div>
        <div class="progress-bar">
          <div class="progress-fill"></div>
        </div>
        ${this.options.showDetails ? '<div class="progress-details"></div>' : ''}
        <div class="progress-controls">
          <button class="progress-cancel-btn" title="取消操作">${SYMBOLS.UI.CLOSE} 取消</button>
        </div>
      </div>
    `)

    // 添加到容器
    $container.append(this.$progressElement)

    // 绑定事件
    this.bindEvents()

    // 应用初始样式
    createStandardStyleTag(this.cssStyleId, this.styles())
    this.updateProgressDisplay()

    // 初始隐藏
    this.hide()
  }

  /**
   * 绑定事件
   */
  private bindEvents(): void {
    if (!this.$progressElement)
      return

    // 取消按钮点击事件
    this.$progressElement.find('.progress-cancel-btn').on('click', () => {
      this.cancel('用户取消操作')
    })
  }

  /**
   * 更新进度显示
   */
  private updateProgressDisplay(): void {
    if (!this.$progressElement)
      return

    const { stage, message, percentage, details } = this.currentState

    // 更新内容
    this.$progressElement.find('.progress-message').text(message)
    this.$progressElement.find('.progress-percentage').text(`${Math.round(percentage)}%`)
    this.$progressElement.find('.progress-fill').css('width', `${percentage}%`)

    if (this.options.showDetails)
      this.$progressElement.find('.progress-details').text(details)

    // 更新时间显示
    if (this.options.showElapsedTime)
      this.updateTimeDisplay()

    // 更新图标
    const step = this.predefinedSteps.find(s => s.stage === stage)
    const icon = step?.icon || this.getDefaultIcon(stage)
    this.$progressElement.find('.progress-icon').html(icon || '')

    // 更新阶段类名
    this.$progressElement
      .removeClass('stage-idle stage-collecting stage-analyzing stage-rendering stage-complete stage-error stage-cancelled')
      .addClass(`stage-${stage}`)
  }

  /**
   * 获取默认图标
   */
  private getDefaultIcon(stage: ProgressStage): string {
    const icons = {
      [ProgressStage.IDLE]: SYMBOLS.TIME.CLOCK,
      [ProgressStage.COLLECTING]: SYMBOLS.UI.DOWNLOAD,
      [ProgressStage.ANALYZING]: SYMBOLS.UI.CHART,
      [ProgressStage.RENDERING]: SYMBOLS.UI.COMPUTER,
      [ProgressStage.COMPLETE]: SYMBOLS.STATUS.SUCCESS,
      [ProgressStage.ERROR]: SYMBOLS.STATUS.ERROR,
      [ProgressStage.CANCELLED]: SYMBOLS.UI.CLOSE,
    }
    return icons[stage] || ''
  }

  /**
   * 显示进度
   */
  public show(): void {
    if (!this.$progressElement)
      return

    this.$progressElement.addClass('visible')
    this.isVisible = true
    this.startTime = Date.now()
  }

  /**
   * 隐藏进度
   */
  public hide(): void {
    if (!this.$progressElement)
      return

    this.$progressElement.removeClass('visible')
    this.isVisible = false
  }

  /**
   * 更新进度状态
   */
  public update(state: Partial<Omit<ProgressState, 'timestamp' | 'duration'>>): void {
    this.currentState = {
      ...this.currentState,
      ...state,
      timestamp: Date.now(),
      duration: this.startTime ? Date.now() - this.startTime : 0,
    }

    this.updateProgressDisplay()

    // 自动显示/隐藏逻辑
    if (this.currentState.stage !== ProgressStage.IDLE && !this.isVisible)
      this.show()

    if (this.currentState.stage === ProgressStage.COMPLETE && this.options.autoHide)
      setTimeout(() => this.hide(), this.options.hideDelay)

    logger.debug(`[${this.name}] 进度更新: ${this.currentState.stage} ${this.currentState.percentage}%`, {
      message: this.currentState.message,
      details: this.currentState.details,
    })
  }

  /**
   * 快速更新到预定义步骤
   */
  public updateToStep(stage: ProgressStage, customMessage?: string, customDetails?: string): void {
    const step = this.predefinedSteps.find(s => s.stage === stage)

    if (!step) {
      logger.warn(`[${this.name}] 未找到预定义步骤: ${stage}`)
      return
    }

    this.update({
      stage,
      percentage: step.targetPercentage,
      message: customMessage || step.defaultMessage,
      details: customDetails || '',
    })
  }

  /**
   * 完成进度
   */
  public complete(message?: string, details?: string): void {
    this.stopTimeUpdate() // 停止时间更新

    this.update({
      stage: ProgressStage.COMPLETE,
      percentage: 100,
      message: message || '操作完成！',
      details: details || '',
    })

    logger.debug(`[${this.name}] 操作完成，总耗时: ${ToolKit.time.formatElapsedTime(this.elapsedTime)}`)
  }

  /**
   * 报告错误
   */
  public error(error: Error | string, details?: string): void {
    this.stopTimeUpdate() // 停止时间更新

    this.update({
      stage: ProgressStage.ERROR,
      message: `运行出错`,
      details: details || '',
    })

    logger.debug(`[${this.name}] 操作失败，运行时长: ${ToolKit.time.formatElapsedTime(this.elapsedTime)}`, error)
  }

  /**
   * 取消进度
   */
  public cancel(reason?: string): void {
    if (this._isCancelled)
      return

    this._isCancelled = true
    this.stopTimeUpdate() // 停止时间更新

    this.update({
      stage: ProgressStage.CANCELLED,
      message: '操作已取消',
      details: reason || '用户取消',
      percentage: this.currentState.percentage, // 保持当前进度
    })

    // 执行所有取消回调
    this.cancelCallbacks.forEach((callback) => {
      try {
        callback()
      }
      catch (error) {
        logger.error(`[${this.name}] 取消回调执行失败`, error)
      }
    })

    // 延迟隐藏
    setTimeout(() => this.hide(), 500)

    logger.debug(`[${this.name}] 进度已取消，运行时长: ${ToolKit.time.formatElapsedTime(this.elapsedTime)}`, { reason })
  }

  /**
   * 重置进度
   */
  public reset(): void {
    this.stopTimeUpdate() // 停止时间更新

    // this.previousState = { ...this.currentState }
    this.currentState = this.createInitialState()
    this.startTime = 0

    this.updateProgressDisplay()
    this.hide()

    logger.info(`[${this.name}] 进度已重置`)
  }

  /**
   * 检查是否已取消
   */
  public isCancelled(): boolean {
    return this._isCancelled
  }

  /**
   * 注册取消回调
   */
  public onCancel(callback: () => void): void {
    this.cancelCallbacks.push(callback)
  }

  /**
   * 重置取消状态
   */
  public resetCancellation(): void {
    this._isCancelled = false
    this.cancelCallbacks = []
  }

  /**
   * 启动时间更新
   */
  private startTimeUpdate(): void {
    this.startTime = Date.now()
    this.elapsedTime = 0

    this.timerManager.createTimerTask({
      id: this.timeUpdateTaskId,
      interval: 1000,
      callback: () => {
        this.elapsedTime = Date.now() - this.startTime
        this.updateTimeDisplay()
      },
      immediate: true,
    })
  }

  /**
   * 停止时间更新
   */
  private stopTimeUpdate(): void {
    this.timerManager.clearInterval(this.timeUpdateTaskId)
  }

  /**
   * 更新时间显示
   */
  private updateTimeDisplay(): void {
    if (!this.$progressElement || !this.options.showElapsedTime)
      return

    const timeElement = this.$progressElement.find('.progress-time')

    if (!timeElement.length)
      return

    timeElement.text(ToolKit.time.formatElapsedTime(this.elapsedTime, this.options.timeFormat))
  }

  /**
   * 获取当前状态
   */
  public getState(): ProgressState {
    return { ...this.currentState }
  }

  /**
   * 销毁进度管理器
   */
  public destroy(): void {
    this.stopTimeUpdate() // 停止时间更新

    if (this.$progressElement) {
      this.$progressElement.remove()
      this.$progressElement = null
    }

    removeStandardStyleTag(this.cssStyleId)
    logger.info(`[${this.name}] 进度管理器已销毁`)
  }

  /**
   * 生成样式
   */
  private styles(): string {
    return `
      .${this.containerClassName} {
        position: fixed;
        bottom: 20px;
        left: 20px;
        background: var(--${PROJECT_PREFIX}-theme-loading-alert-bg) !important;
        color: var(--${PROJECT_PREFIX}-theme-loading-alert-text) !important;
        padding: 10px 15px;
        border-radius: 4px;
        z-index: 1000;
        font-size: 14px !important;
        width: 300px;
        transition: all ${this.options.animationDuration}ms ease;
        opacity: 0;
        
        &.visible {
          opacity: 1;
        }
        
        .progress-header {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 12px 16px;
          white-space: nowrap;
          
          .progress-icon {
            font-size: 16px;
            margin-right: 8px;
          }

          .progress-message {
            flex: 1;
            font-weight: 600;
            color: var(${this.themeVarService.default.text.primary});
            margin-right: 12px;
          }
          
          .progress-stats {
            display: flex;
            align-items: center;
            gap: 12px;
            font-size: 12px;
            
            .progress-percentage {
              font-weight: 600;
              color: var(${this.themeVarService.default.text.secondary});
              font-size: 12px;
              text-align: right;
            }
            
            .progress-time {
              color: var(${this.themeVarService.default.text.secondary});
              min-width: 60px;
              text-align: right;
              font-family: 'Monaco', 'Consolas', monospace;
            }
          }
        }
        
        .progress-bar {
          height: 4px;
          background: var(${this.themeVarService.default.text.neutral});
          border-radius: 2px;
          margin: 0 16px;
          overflow: hidden;
          
          .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, var(${this.themeVarService.message.orange.textPrimary}) 0%, var(${this.themeVarService.message.success.textPrimary}) 100%);
            border-radius: 2px;
            transition: width ${this.options.animationDuration}ms ease;
            width: 0%;
          }
        }

        .progress-details {
          padding: 8px 16px;
          font-size: 12px;
          color: var(${this.themeVarService.default.text.secondary});
          line-height: 1.4;
        }
        
        .progress-controls {
          padding: 8px 16px;
          text-align: right;

          .progress-cancel-btn {
            background: none;
            border: 1px solid var(${this.themeVarService.default.border.colorNeutral});
            color: var(${this.themeVarService.default.text.secondary});
            cursor: pointer;
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 12px;
            
            &:hover {
              color: var(${this.themeVarService.message.danger.textPrimary});
            }
          }
        }
        
        /* 阶段样式 */
        &.stage-complete, &.stage-error, &.stage-cancelled {
          .progress-controls .progress-cancel-btn {
            display: none !important;
          }
        }
        
        &.stage-complete .progress-fill {
          background: var(${this.themeVarService.message.success.textPrimary});
        }

        &.stage-error .progress-fill {
          background: var(${this.themeVarService.message.danger.textPrimary});
        }

        &.stage-cancelled .progress-fill {
          background: var(${this.themeVarService.message.warning.textPrimary});
        }
      }
    `
  }
}
